package com.qjc.demo.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @Description: http请求
 * @Author: qjc
 * @Date: 2020/8/1 16:27
 */
@Slf4j
public class HttpClientHelper {


    private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000)
            .setConnectionRequestTimeout(15000).build();

    private static HttpClientHelper instance = null;

    public HttpClientHelper() {
    }

    /**
     * 使用httpclint 发送文件，如果不传输文件，直接设置fileParams=null，
     * 如果不设置请求头参数，直接设置headerParams=null，就可以进行普通参数的POST请求了
     *
     * @param url          请求路径
     * @param fileParams   文件参数
     * @param otherParams  其他字符串参数
     * @param headerParams 请求头参数
     * @return
     */
    public static String uploadFile(String url, Map<String, MultipartFile> fileParams, Map<String, String> otherParams, Map<String, String> headerParams) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            //设置请求头
            if (headerParams != null && headerParams.size() > 0) {
                for (Map.Entry<String, String> e : headerParams.entrySet()) {
                    String value = e.getValue();
                    String key = e.getKey();
                    if (StringUtils.isNotBlank(value)) {
                        httpPost.setHeader(key, value);
                    }
                }
            }
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(Charset.forName("utf-8"));
            //加上此行代码解决返回中文乱码问题
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            //	文件传输http请求头(multipart/form-data)
            if (fileParams != null && fileParams.size() > 0) {
                for (Map.Entry<String, MultipartFile> e : fileParams.entrySet()) {
                    String fileParamName = e.getKey();
                    MultipartFile file = e.getValue();
                    if (file != null) {
                        String fileName = file.getOriginalFilename();
                        // 文件流
                        builder.addBinaryBody(fileParamName, file.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, fileName);
                    }
                }
            }
            //	字节传输http请求头(application/json)
            ContentType contentType = ContentType.create("application/json", Charset.forName("UTF-8"));
            if (otherParams != null && otherParams.size() > 0) {
                for (Map.Entry<String, String> e : otherParams.entrySet()) {
                    String value = e.getValue();
                    if (StringUtils.isNotBlank(value)) {
                        // 类似浏览器表单提交，对应input的name和value
                        builder.addTextBody(e.getKey(), value, contentType);
                    }
                }
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            // 执行提交
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                // 将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public void setTimeOut(Integer span) {
        requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000)
                .setConnectionRequestTimeout(span).build();
    }

    public static HttpClientHelper getInstance() {
        if (instance == null) {
            instance = new HttpClientHelper();
        }
        return instance;
    }

    public String sendJsonHttpPost(String url, String json) {

        CloseableHttpClient httpclient = HttpClients.createDefault();
        String responseInfo = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            ContentType contentType = ContentType.create("application/json", CharsetUtils.get("UTF-8"));
            httpPost.setEntity(new StringEntity(json, contentType));
            httpPost.setConfig(requestConfig);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            int status = response.getStatusLine().getStatusCode();
            int successStatus = 200;
            int errorStatus = 300;
            if (status >= successStatus && status < errorStatus) {
                if (null != entity) {
                    responseInfo = EntityUtils.toString(entity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseInfo;
    }

    /**
     * 以流的方式发送文件
     *
     * @param url
     * @param file
     * @return
     */
    public String sendFileHttpPost(String url, MultipartFile file) {
        BufferedReader in;
        DataOutputStream out;
        String result = "";
        try {
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Content-Type", "application/octet-stream");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST"); // 设置请求方式
            out = new DataOutputStream(conn.getOutputStream());
            out.write(file.getBytes());
            out.flush();
            out.close();
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (IOException e) {
            log.error("发送文件/图片出现异常", e);
        }
        return result;
    }

}